package sync;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.*;
import java.util.concurrent.atomic.*;
import java.util.concurrent.locks.*;

public class AsyncSafety {

    // 1. 线程安全的集合示例
    public static void threadSafeCollections() throws InterruptedException {
        // 线程安全的List
        List<String> synchronizedList = Collections.synchronizedList(new ArrayList<>());
        List<String> concurrentList = new CopyOnWriteArrayList<>();
        
        // 线程安全的Map
        Map<String, Integer> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
        Map<String, Integer> concurrentMap = new ConcurrentHashMap<>();
        
        // 线程安全的Set
        Set<String> synchronizedSet = Collections.synchronizedSet(new HashSet<>());
        Set<String> concurrentSet = new CopyOnWriteArraySet<>();
        
        // 使用示例
        Thread[] threads = new Thread[10];
        for (int t = 0; t < 10; t++) {
            final int threadIndex = t;
            threads[t] = new Thread(() -> {
                for (int i = 0; i < 100; i++) {
                    String key = "key-" + threadIndex + "-" + i;
                    Integer value = i;
                    
                    // 安全地添加到集合
                    synchronizedList.add(key);
                    concurrentList.add(key);
                    
                    synchronizedMap.put(key, value);
                    concurrentMap.put(key, value);
                    
                    synchronizedSet.add(key);
                    concurrentSet.add(key);
                }
            });
            threads[t].start();
        }
        
        // 等待所有线程完成
        for (Thread thread : threads) {
            thread.join();
        }
        
        System.out.println("synchronizedList size: " + synchronizedList.size());
        System.out.println("concurrentList size: " + concurrentList.size());
        System.out.println("synchronizedMap size: " + synchronizedMap.size());
        System.out.println("concurrentMap size: " + concurrentMap.size());
        System.out.println("synchronizedSet size: " + synchronizedSet.size());
        System.out.println("concurrentSet size: " + concurrentSet.size());
//         ===== 线程安全的集合示例 =====
// synchronizedList size: 1000
// concurrentList size: 1000
// synchronizedMap size: 1000
// concurrentMap size: 1000
// synchronizedSet size: 1000
// concurrentSet size: 1000
    }

    // 2. 原子操作示例
    public static void atomicOperations() throws InterruptedException {
        AtomicInteger counter = new AtomicInteger(0);
        AtomicLong longCounter = new AtomicLong(0);
        AtomicReference<String> reference = new AtomicReference<>("initial");
        
        Thread[] threads = new Thread[10];
        for (int t = 0; t < 10; t++) {
            final int threadIndex = t;
            threads[t] = new Thread(() -> {
                for (int i = 0; i < 1000; i++) {
                    // 原子递增
                    counter.incrementAndGet();
                    longCounter.incrementAndGet();
                    
                    // 原子更新引用
                    reference.updateAndGet(current -> current + "-" + threadIndex);
                    
                    // 比较并设置 (CAS)
                    int current;
                    int newValue;
                    do {
                        current = counter.get();
                        newValue = current + 1;
                    } while (!counter.compareAndSet(current, newValue));
                }
            });
            threads[t].start();
        }
        
        for (Thread thread : threads) {
            thread.join();
        }
        
        System.out.println("Final counter: " + counter.get());
        System.out.println("Final longCounter: " + longCounter.get());
        // System.out.println("Final reference: " + reference.get());
// ===== 原子操作示例 =====
// Final counter: 20000
// Final longCounter: 10000
    }

    // 3. 使用锁进行同步
    public static void lockSynchronization() throws InterruptedException {
        ReentrantLock lock = new ReentrantLock();
        Condition condition = lock.newCondition();
        int[] sharedResource = {0}; // 使用数组来模拟可变引用
        
        Thread producer = new Thread(() -> {
            lock.lock();
            try {
                // 修改共享资源
                sharedResource[0] = 42;
                System.out.println("Producer: 设置资源值为 " + sharedResource[0]);
                
                // 通知消费者
                condition.signal();
            } finally {
                lock.unlock();
            }
        });
        
        Thread consumer = new Thread(() -> {
            lock.lock();
            try {
                // 等待资源准备好
                while (sharedResource[0] == 0) {
                    System.out.println("Consumer: 等待资源...");
                    try {
                        condition.await();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
                
                // 使用共享资源
                System.out.println("Consumer: 消费资源值 " + sharedResource[0]);
            } finally {
                lock.unlock();
            }
        });
        
        consumer.start();
        Thread.sleep(100); // 确保消费者先启动
        producer.start();
        
        producer.join();
        consumer.join();
        //===== 锁同步示例 =====
// Consumer: 等待资源...
// Producer: 设置资源值为 42
// Consumer: 消费资源值 42
    }

    // 4. 读写锁示例
    public static void readWriteLockExample() throws InterruptedException {
        ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        Lock readLock = readWriteLock.readLock();
        Lock writeLock = readWriteLock.writeLock();
        
        List<Integer> sharedData = new ArrayList<>();
        
        // 写操作 - 独占锁
        Thread writer = new Thread(() -> {
            for (int i = 0; i < 5; i++) {
                writeLock.lock();
                try {
                    System.out.println("Writer: 添加数据 " + i);
                    sharedData.add(i);
                    try {
                        Thread.sleep(100); // 模拟写操作耗时
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                } finally {
                    writeLock.unlock();
                }
            }
        });
        
        // 读操作 - 共享锁
        Thread[] readers = new Thread[3];
        for (int r = 0; r < 3; r++) {
            final int readerId = r;
            readers[r] = new Thread(() -> {
                for (int i = 0; i < 3; i++) {
                    readLock.lock();
                    try {
                        System.out.println("Reader " + readerId + ": 读取数据 " + sharedData);
                        try {
                            Thread.sleep(50); // 模拟读操作耗时
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    } finally {
                        readLock.unlock();
                    }
                    try {
                        Thread.sleep(100); // 读取间隔
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
            readers[r].start();
        }
        
        writer.start();
        
        writer.join();
        for (Thread reader : readers) {
            reader.join();
        }
        // ===== 读写锁示例 =====
// Reader 2: 读取数据 []
// Reader 0: 读取数据 []
// Reader 1: 读取数据 []
// Writer: 添加数据 0
// Writer: 添加数据 1
// Writer: 添加数据 2
// Writer: 添加数据 3
// Writer: 添加数据 4
// Reader 1: 读取数据 [0, 1, 2, 3, 4]
// Reader 0: 读取数据 [0, 1, 2, 3, 4]
// Reader 2: 读取数据 [0, 1, 2, 3, 4]
// Reader 1: 读取数据 [0, 1, 2, 3, 4]
// Reader 2: 读取数据 [0, 1, 2, 3, 4]
// Reader 0: 读取数据 [0, 1, 2, 3, 4]
    }

    // 5. 线程安全的延迟初始化（双重检查锁定）
    static class SafeLazyInitialization {
        private volatile static String instance = null;
        
        public static String getInstance() {
            if (instance == null) {
                synchronized (SafeLazyInitialization.class) {
                    if (instance == null) {
                        System.out.println("安全延迟初始化执行");
                        instance = "安全初始化的值";
                    }
                }
            }
            return instance;
        }
    }

    // 6. 使用ThreadLocal实现线程局部变量
    public static void threadLocalExample() throws InterruptedException {
        ThreadLocal<Integer> threadLocal = new ThreadLocal<>();
        
        Thread[] threads = new Thread[3];
        for (int t = 0; t < 3; t++) {
            final int threadId = t;
            threads[t] = new Thread(() -> {
                // 每个线程设置自己的值
                threadLocal.set(threadId * 10);
                System.out.println("线程 " + threadId + " 设置值: " + threadLocal.get());
                
                // 模拟一些处理
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                
                // 再次获取值，验证每个线程只能访问自己的值
                System.out.println("线程 " + threadId + " 再次获取值: " + threadLocal.get());
                
                // 使用完毕后清除，避免内存泄漏
                threadLocal.remove();
            });
            threads[t].start();
        }
        
        for (Thread thread : threads) {
            thread.join();
        }
    }

    // 7. 使用CountDownLatch进行线程协调
    public static void countDownLatchExample() throws InterruptedException {
        int threadCount = 5;
        CountDownLatch startSignal = new CountDownLatch(1);
        CountDownLatch doneSignal = new CountDownLatch(threadCount);
        
        for (int i = 0; i < threadCount; i++) {
            final int workerId = i;
            new Thread(() -> {
                try {
                    System.out.println("工作线程 " + workerId + " 准备就绪");
                    startSignal.await(); // 等待开始信号
                    System.out.println("工作线程 " + workerId + " 开始工作");
                    
                    // 模拟工作
                    Thread.sleep((long) (Math.random() * 1000));
                    
                    System.out.println("工作线程 " + workerId + " 完成工作");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } finally {
                    doneSignal.countDown(); // 通知完成
                }
            }).start();
        }
        
        // 给工作线程一些时间准备
        Thread.sleep(500);
        System.out.println("主线程发出开始信号");
        startSignal.countDown();
        
        System.out.println("主线程等待所有工作线程完成");
        doneSignal.await();
        System.out.println("所有工作线程已完成");
    }

    // 8. 使用CyclicBarrier进行线程同步
    public static void cyclicBarrierExample() throws InterruptedException {
        int threadCount = 3;
        CyclicBarrier barrier = new CyclicBarrier(threadCount, () -> {
            // 当所有线程到达屏障时执行
            System.out.println("所有线程已到达屏障点，继续执行");
        });
        
        for (int i = 0; i < threadCount; i++) {
            final int threadId = i;
            new Thread(() -> {
                try {
                    System.out.println("线程 " + threadId + " 正在执行第一阶段");
                    Thread.sleep((long) (Math.random() * 1000));
                    System.out.println("线程 " + threadId + " 到达第一个屏障点");
                    
                    barrier.await(); // 等待所有线程到达第一个屏障点
                    
                    System.out.println("线程 " + threadId + " 正在执行第二阶段");
                    Thread.sleep((long) (Math.random() * 1000));
                    System.out.println("线程 " + threadId + " 到达第二个屏障点");
                    
                    barrier.await(); // 等待所有线程到达第二个屏障点
                    
                    System.out.println("线程 " + threadId + " 完成所有工作");
                } catch (InterruptedException | BrokenBarrierException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }

    // 主函数
    public static void main(String[] args) throws InterruptedException {
        System.out.println("===== 线程安全的集合示例 =====");
        threadSafeCollections();
        
        System.out.println("\n===== 原子操作示例 =====");
        atomicOperations();
        
        System.out.println("\n===== 锁同步示例 =====");
        lockSynchronization();
        
        System.out.println("\n===== 读写锁示例 =====");
        readWriteLockExample();
        
        System.out.println("\n===== 线程安全的延迟初始化 =====");
        System.out.println("第一次访问: " + SafeLazyInitialization.getInstance());
        System.out.println("第二次访问: " + SafeLazyInitialization.getInstance());
        
        System.out.println("\n===== ThreadLocal示例 =====");
        threadLocalExample();
        
        System.out.println("\n===== CountDownLatch示例 =====");
        countDownLatchExample();
        
        System.out.println("\n===== CyclicBarrier示例 =====");
        cyclicBarrierExample();
        
        // 等待CyclicBarrier示例完成
        Thread.sleep(5000);
    }
}